import { App, ComponentType, Layout, Micro } from "@/seed-application/types"
import { upperFirst } from 'lodash-es'
import { router } from "@/router"
import Container from "../Container"
import { componentManager } from "../SeedApplication"

const LAYOUT_ROUTE_NAME = 'Layout'

export class RouteManager {
  private app: App

  public init(app: App) {
    this.app = app
    this.addRoutes()
  }

  private addRoutes() {
    this.addLoginRoute()
    this.addLayoutRoute()
    this.addDefaultHomeRoute()
  
    this.addActionRoutes()
    this.addHomeRoutes()
    this.addSeedRoutes()
  
    const micros = this.app.micros
    if(micros) {
      for(const microName in micros) {
        const micro = micros[microName]
        this.addMicroLayoutRoute(micro)
        this.addMicroActionRoutes(micro)
        this.addMicroHomeRoutes(micro)
        this.addMicroSeedRoutes(micro)
      }
    }
  
    this.addErrorRoute()
    this.addRedirectRoute()
  }
  
  private addLoginRoute() {
    const name = 'Login'
    const meta = { affix: false, breadcrumb: false, noTagsView: true, label: '用户登录' }
    const [component, props] = this.getComponent('login', this.app.login, this.app.loginProps, this.app.loginLayout)
    router.addRoute({ name, path: `/login`, component, props, meta })
  }
  
  private addLayoutRoute() {
    const layoutName = LAYOUT_ROUTE_NAME
    const [component, props] = this.getComponent('layout', this.app.component, this.app.componentProps, this.app.layout)
    router.addRoute({name: layoutName, path: '/', component, props})
  }
  
  private addMicroLayoutRoute(micro: Micro) {
    const layoutName = upperFirst(micro.name)
    const [component, props] = this.getComponent('layout', micro.component, micro.componentProps, micro.layout)
    router.addRoute({name: layoutName, path: `/${micro.name}`, component, props})
  }
  
  private addDefaultHomeRoute() {
    const homeName = 'Home'
    const [homeComponent, homeComponentProps] = this.getComponent('home', this.app.home, this.app.homeProps, this.app.homeLayout)
    const meta = { affix: true, breadcrumb: false, noTagsView: false, label: `首页`, icon: 'bxs:home' }
    router.addRoute(LAYOUT_ROUTE_NAME, { name: homeName, path: '', component: homeComponent, props: homeComponentProps, meta })
  }
  
  private addActionRoutes() {
    const actions = this.app.actions
    if(!actions) return
    console.log('actions=========', actions)
    for(const action of actions) {
      const actionName = action.name
      const name: string = upperFirst(actionName)
      const componentProps = { ...(action.componentProps || {}), actionName }
      const [component, props] = this.getComponent(action.type, action.component, componentProps, action.layout)
      const { label, icon } = action
      const meta = {
          affix: false,
          // hidden: false,
          breadcrumb: true,
          noTagsView: false,
          // position: position || 'menu',
          mode: action.mode,
          label: label || name,
          icon: icon || 'bxs:setting'
        }
      router.addRoute(LAYOUT_ROUTE_NAME, { name, path: actionName, component, props, meta })
    }
  }
  
  private addMicroActionRoutes(micro: Micro) {
    const actions = micro.actions
    if(!actions) return
  
    for(const action of actions) {
      const actionName = action.name
      const name: string = upperFirst(actionName)
      const componentProps = { ...(action.componentProps || {}), actionName: action.name, microName: micro.name }
      const [component, props] = this.getComponent(action.type, action.component, componentProps, action.layout)
      const { label, icon } = action
      const meta = {
          affix: false,
          // hidden: false,
          breadcrumb: true,
          noTagsView: false,
          // position: position || 'menu',
          mode: action.mode,
          label: label || name,
          icon: icon || 'bxs:setting'
        }
      router.addRoute(upperFirst(micro.name), { name, path: actionName, component, props, meta })
    }
  }
  
  private addHomeRoutes() {
    const homes = this.app.homes
    if(!homes) return
    
    for(const homeName in homes) {
      const name = upperFirst(homeName)
      const home = homes[homeName]
      const [component, props] = this.getComponent('home', home.component, home.componentProps, home.layout)
      const { affix, breadcrumb, noTagsView, label, icon } = home
      const meta = {
        affix: affix == void 0 ? false : affix,
        // hidden: hidden == void 0 ? false : hidden,
        breadcrumb: breadcrumb == void 0 ? true : breadcrumb,
        noTagsView: noTagsView == void 0 ? false : noTagsView,
        // position: position || 'menu',
        mode: home.mode,
        label: label || `首页`,
        icon: icon || 'bxs:home'
      }
      router.addRoute(LAYOUT_ROUTE_NAME, { name, path: homeName, component, props, meta })
    }
  }
  
  private addMicroHomeRoutes(micro: Micro) {
    const homes = micro.actions
    if(!homes) return
  
    for(const homeName in homes) {
      const name = upperFirst(homeName)
      const home = homes[homeName]
      const componentProps = { ...(home.componentProps || {}), microName: micro.name }
      const [component, props] = this.getComponent('home', home.component, componentProps, home.layout)
      const { affix, breadcrumb, noTagsView, label, icon } = home
      const meta = {
        affix: affix == void 0 ? false : affix,
        // hidden: hidden == void 0 ? false : hidden,
        breadcrumb: breadcrumb == void 0 ? true : breadcrumb,
        noTagsView: noTagsView == void 0 ? false : noTagsView,
        // position: position || 'menu',
        mode: home.mode,
        label: label || `首页`,
        icon: icon || 'bxs:home'
      }
      router.addRoute(upperFirst(micro.name), { name, path: homeName, component, props, meta })
    }
  }
  
  private addSeedRoutes() {
    const seeds = this.app.seeds
    if(!seeds) return
  
    for(const seedName in seeds) {
      const seed = seeds[seedName]
      if(seed.type != 'module' || !this.app.tenant && seed.name === 'tenant') continue

      const name = upperFirst(seedName)
      const { affix, breadcrumb, noTagsView, icon, label } = seed
      const componentProps = { ...(seed.componentProps || {}), seedName: seed.name }
      const [component, props] = this.getComponent('seed', seed.component, componentProps, seed.layout)
      const meta = {
        affix: affix == void 0 ? false : affix,
        // hidden: hidden == void 0 ? false : hidden,
        breadcrumb: breadcrumb == void 0 ? true : breadcrumb,
        noTagsView: noTagsView == void 0 ? false : noTagsView,
        // position: position || 'menu',
        mode: seed.mode,
        icon: icon || 'bxs:home',
        label: `${label}管理`
      }
      router.addRoute(LAYOUT_ROUTE_NAME, { name, path: seedName, component, props, meta })
    }
  }
  
  private addMicroSeedRoutes(micro: Micro) {
    const seeds = micro.seeds
    if(!seeds) return
  
    for(const seedName in seeds) {
      const seed = seeds[seedName]
      if(seed.type != 'module') continue
  
      const name = upperFirst(seedName)
      const { affix, breadcrumb, noTagsView, icon, label } = seed
      const componentProps = { ...(seed.componentProps || {}), seedName: seed.name, microName: micro.name }
      const [component, props] = this.getComponent('seed', seed.component, componentProps, seed.layout)
      const meta = {
        affix: affix == void 0 ? false : affix,
        // hidden: hidden == void 0 ? false : hidden,
        breadcrumb: breadcrumb == void 0 ? true : breadcrumb,
        noTagsView: noTagsView == void 0 ? false : noTagsView,
        // position: position || 'menu',
        mode: seed.mode,
        icon: icon || 'bxs:home',
        label: `${label}管理`
      }
      router.addRoute(upperFirst(micro.name), { name, path: seedName, component, props, meta })
    }
  }
  
  private addErrorRoute() {  
    const name = 'Error'
    const meta = { affix: false, breadcrumb: false, noTagsView: true, title: '404' }
    const [component, props] = this.getComponent('error', this.app.error, this.app.errorProps, this.app.errorLayout)
    router.addRoute({ name, path: `/404`, component, props, meta })
  }
  
  private addRedirectRoute() {
    const name = 'Redirect'
    const meta = { affix: false, breadcrumb: false, noTagsView: true }
    const [component, props] = this.getComponent('redirect', this.app.redirect, this.app.redirectProps, this.app.redirectLayout)
    router.addRoute({ name, path: `/redirect/:path(.*)`, component, props, meta })
  }

  private getComponent(type: ComponentType, component: string, props?: Record<string, any>, layout?: Layout) {
    return layout ? [Container, { layout, props }] : [componentManager.getComponent(type, component), props]
  }
}